home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
c
/
str.exe
/
STR.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-17
|
23KB
|
870 lines
//
// str.cpp : str class implementation
// Author : Roy S. Woll
//
// Copyright (c) 1993 by Roy S. Woll
// You may distribute this source freely as long as you leave all files
// in their original form, including the copyright notice as is.
//
//
// Version 2.11 3/17/93
// Friend operator ">>" changed to use str's buffer if > 256.
// Assign operator optimized to not copy referenced data.
// Fix - Remove member function now transfers only necessary characters
//
// Version 2.00 12/5/92
// Support searching/replacing, regular expressions, case sensitivity
//
// Fixed the following bugs.
// 1. Fixed size strings
// 2. Concatenating a substr
//
// Changed member functions pad/strip to modify instance, and introduced
// friend functions pad/strip.
//
// Version 1.00 10/20/92
//
#include <ctype.h>
#include <string.h>
#include <iostream.h>
#include <iomanip.h>
#include <assert.h>
#include "str.h"
#include "dynstream.h"
int strnicmp(const char * s1, const char * s2, unsigned n);
int stricmp(const char * s1, const char * s2);
char * strlwr(char *);
char * strupr(char *);
inline int min(int x, int y){if (x<y) return x; else return y;}
inline int max(int x, int y){if (x>y) return x; else return y;}
// Define macro used to adjust internal debugging counters for object
#ifdef DEBUG_STR
#define STR_SUB_COUNTERS(count) count--;
#define STR_ADD_COUNTERS(count) count++;Total##count++;
#else
#define STR_SUB_COUNTERS(count)
#define STR_ADD_COUNTERS(count)
#endif
static str::strdata NullData = {0, 0, 1, 0, 1, ""};
// Create and map to new buffer, and if previous buffer exists,
// transfer to new buffer.
// Delete old buffer if unreferenced.
char * str::getNewBuffer(int newbufsize){
return getNewBuffer(length(), newbufsize);
};
char * str::getNewBuffer(int len, int newbufsize)
{
if (data==&NullData){
if (memsize_incr) newbufsize = max(newbufsize, memsize_init);
else newbufsize = memsize_init;
}
else {
if (!memsize_incr) return NULL;
if ((newbufsize>data->cursize) || (!newbufsize) )
newbufsize = max(newbufsize, data->cursize + memsize_incr);
else newbufsize = max(newbufsize, memsize_init);
}
if (!newbufsize) newbufsize = memsize_incr; // don't allow 0 size
strdata * newdata;
init(newdata, newbufsize, 0);
setNewBuffer(newdata, newbufsize, len);
return data->buf;
};
// Map to new buffer and if previous buffer exists, transfer to new buffer
void str::setNewBuffer(strdata * newdata,
int newbufsize, int len){
newdata->curlength = data->curlength;
newdata->strChange = data->strChange;
if (data->mystream) {
// Use existing stream
newdata->mystream = data->mystream;
// update existing stream to map to new buffer
newdata->mystream->rdbuf()->setNewBuffer(newdata->buf, newbufsize);
// update stream length next time stream is called for previous data
if (!data->strChange){
data->strChange = 1;
data->curlength = data->mystream->rdbuf()->out_waiting();
};
// force previous data to have unitialized stream
data->mystream = NULL;
};
memcpy(newdata->buf, data->buf, len);
if (!(--data->refcount)) {
delete data;
STR_SUB_COUNTERS(AllocationCount)
}
data = newdata;
};
void str::init(strdata*& adata, int cursize,
int curlength)
{
STR_ADD_COUNTERS(AllocationCount)
if (!cursize) cursize=STR_DEFAULT_MEMINCR;
adata =
(strdata *) new char [(cursize+1)+
sizeof(strdata)-strdata::STR_DEBUG_BUFSIZE];
if (!adata){
cout << "Failed to allocate memory (" << cursize << ")" << endl;
assert(adata);
};
adata->cursize=cursize;
adata->curlength=curlength;
adata->refcount=1;
adata->mystream=NULL;
adata->strChange=1;
};
// Construct an empty str
str::str (void):
data(&NullData),
memsize_init(0), memsize_incr(STR_DEFAULT_MEMINCR),
flags(defaultFlags)
{
STR_ADD_COUNTERS(ObjectCount)
data->refcount++;
};
// Construct an empty str
str::str (int p_bufsize, int p_incr):
data(&NullData),
memsize_init(p_bufsize), memsize_incr(p_incr),
flags(defaultFlags)
{
STR_ADD_COUNTERS(ObjectCount)
data->refcount++;
};
// Construct a str containing substr, char *
str::str (const char * s1, const char * s2):
memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
flags(defaultFlags)
{
STR_ADD_COUNTERS(ObjectCount)
int len1=(s1 ? strlen(s1) : 0);
int len2=(s2 ? strlen(s2) : 0);
init(data, len1+len2, len1+len2);
memcpy(data->buf, s1, len1);
memcpy(data->buf+len1, s2, len2);
};
// Construct a str containing char *, substr
str::str (const char * s1, const substr& s2):
memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
flags(defaultFlags)
{
STR_ADD_COUNTERS(ObjectCount)
int len1=(s1 ? strlen(s1) : 0);
int len2=s2.length();
init(data, len1+len2, len1+len2);
memcpy(data->buf, s1, len1);
memcpy(data->buf+len1, &s2.mystr->data->buf[s2.posReplace], len2);
};
// Construct a str containing two char *
str::str (const substr& s1, const char * s2):
memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
flags(defaultFlags)
{
STR_ADD_COUNTERS(ObjectCount)
int len1= s1.length();
int len2= (s2 ? strlen(s2) : 0);
init(data, len1+len2, len1+len2);
memcpy(data->buf, &s1.mystr->data->buf[s1.posReplace], len1);
memcpy(data->buf+len1, s2, len2);
};
// Construct a str containing two substr
str::str (const substr& s1, const substr& s2):
memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
flags(defaultFlags)
{
STR_ADD_COUNTERS(ObjectCount)
int len1= s1.length();
int len2= s2.length();
init(data, len1+len2, len1+len2);
memcpy(data->buf, &s1.mystr->data->buf[s1.posReplace], len1);
memcpy(data->buf+len1, &s2.mystr->data->buf[s2.posReplace], len2);
};
// Construct a str containing char *
str::str (const char * s, int p_bufsize, int p_incr):
memsize_init(p_bufsize),memsize_incr(p_incr),
flags(defaultFlags)
{
STR_ADD_COUNTERS(ObjectCount)
if (!s) return;
int curlength, cursize;
if (memsize_incr==0) { // not allowed to expand
curlength = min(strlen(s), memsize_init);
cursize = memsize_init;
}
else {
curlength=strlen(s);
cursize = max(curlength, memsize_init);
};
init(data, cursize, curlength);
memcpy(data->buf, s, curlength);
};
// Construct a str containing str
str::str (const str& s, int p_bufsize, int p_incr):
memsize_init(p_bufsize),memsize_incr(p_incr),
flags(defaultFlags)
{
STR_ADD_COUNTERS(ObjectCount)
if (memsize_incr) {
data = s.data;
data->refcount++;
}
else {
int curlength = min(s.length(), memsize_init);
init(data, memsize_init, curlength);
memcpy(data->buf, s, curlength);
};
};
// Return a ostream that maps to the same buffer as the str
ostream& str::stream(int pos){
return stream().seekp(pos);
};
// Return a ostream that maps to the same buffer as the str
ostream& str::stream(void){
//
// check if need to allocate more memory
//
int allocsize=0;
if (data==&NullData) allocsize = memsize_init; // first time allocating
else if (length()>=size()) allocsize = size()+memsize_incr;
_checkMemAllocation(allocsize);
//
// Create stream if it doesn't exist
// otherwise tell dynstream about me in case it needs to extend buf
//
if (!data->mystream) data->mystream = new dynstream(this);
else data->mystream->rdbuf()->set_str(this);
//
// update stream length if length has been changed by str operators.
// Not done every time in case stream operation was the last operation
// to change the leng